import path from 'path'
import KoaRouter from 'koa-router'
import glob from 'glob'
import {changeToArr, convert} from '../utils/common'
import * as R from 'ramda'

const pathPrefix = Symbol('pathPrefix')
export const apiPrefix = '/api'

let routeMap = []

export class Router {
  constructor(app, routePath) {
    this.router = new KoaRouter()
    this.app = app
    this.routePath = routePath
  }

  init() {
    const { app, router, routePath } = this
    glob.sync(path.resolve(routePath, '**/*.js')).forEach(require)

    routeMap.forEach(route => {
      const prefix = route.target[pathPrefix]
      router[route.method](prefix + route.path, ...route.callback)
    })

    app.use(router.routes())
    app.use(router.allowedMethods())
  }
}

// 类修饰器
export function Controller(rPath) {
  // 这里的target就是类本身
  return function(target) {
    target.prototype[pathPrefix] = apiPrefix + rPath
  }
}

// 类方法修饰器
export function setRouter(method) {
  return function(rPath) {
    return function(target, key, descriptor) {
      // 这里的target就是prototype
      routeMap.push({
        target,
        method,
        path: rPath,
        callback: changeToArr(descriptor.value)
      })
      return descriptor
    }
  }
}

export const Get = setRouter('get')
export const Post = setRouter('post')
export const All = setRouter('all')

/*
* @required({
*   body: ['username', 'password']
* })
* */
export const required = obj => convert(async (ctx, next) => {
  let errs = []
  R.forEachObjIndexed((val, key) => {
    errs = errs.concat(obj[key].filter(
      name => !R.has(name)(ctx.request[key]) || R.isEmpty(ctx.request[key][name])
    ))
  })(obj)
  if (errs.length) {
    ctx.throw(400, errs.join(',') + ' is required')
  } else {
    await next()
  }
})
